﻿using CoreWCF;
using SD.IdentitySystem;
using SD.Infrastructure.DTOBase;
using SD.Infrastructure.Membership;
using SlamDunk.MES.AppService.Maps;
using SlamDunk.MES.Domain.Entities.DefinitionContext;
using SlamDunk.MES.Domain.Entities.FoundationContext;
using SlamDunk.MES.Domain.IRepositories;
using SlamDunk.MES.Domain.Mediators;
using SlamDunk.MES.IAppService.DTOs.Inputs;
using SlamDunk.MES.IAppService.DTOs.Outputs.DefinitionContext;
using SlamDunk.MES.IAppService.DTOs.Outputs.FoundationContext;
using SlamDunk.MES.IAppService.DTOs.Outputs.ResourceContext;
using SlamDunk.MES.IAppService.Interfaces;
using SlamDunk.ValueObjects.Enums;
using SlamDunk.ValueObjects.Structs;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SlamDunk.MES.AppService.Implements
{
    /// <summary>
    /// 产品定义服务契约实现
    /// </summary>
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IncludeExceptionDetailInFaults = true)]
    public class DefinitionContract : IDefinitionContract
    {
        #region # 字段及构造器

        /// <summary>
        /// 领域服务中介者
        /// </summary>
        private readonly DomainServiceMediator _svcMediator;

        /// <summary>
        /// 仓储中介者
        /// </summary>
        private readonly RepositoryMediator _repMediator;

        /// <summary>
        /// 单元事务
        /// </summary>
        private readonly IUnitOfWorkMES _unitOfWork;

        /// <summary>
        /// 依赖注入构造器
        /// </summary>
        /// <param name="svcMediator">领域服务中介者</param>
        /// <param name="repMediator">仓储中介者</param>
        /// <param name="unitOfWork">单元事务</param>
        public DefinitionContract(DomainServiceMediator svcMediator, RepositoryMediator repMediator, IUnitOfWorkMES unitOfWork)
        {
            this._svcMediator = svcMediator;
            this._repMediator = repMediator;
            this._unitOfWork = unitOfWork;
        }

        #endregion


        //命令部分

        #region # 创建物料清单 —— void CreateBom(string bomNo, string bomName...
        /// <summary>
        /// 创建物料清单
        /// </summary>
        /// <param name="bomNo">物料清单编号</param>
        /// <param name="bomName">物料清单名称</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        /// <param name="bomItemParams">物料清单项参数模型集</param>
        public void CreateBom(string bomNo, string bomName, string versionNo, Guid productId, decimal runSize, DateTime? effectedDate, DateTime? expiredDate, Guid? facilityId, string description, IEnumerable<BomItemParam> bomItemParams)
        {
            #region # 验证

            bomItemParams = bomItemParams?.ToArray() ?? Array.Empty<BomItemParam>();
            if (!bomItemParams.Any())
            {
                throw new ArgumentNullException(nameof(bomItemParams), "物料清单明细不可为空！");
            }

            #endregion

            IEnumerable<BomItem> bomItems =
                from bomItemParam in bomItemParams
                select new BomItem(bomItemParam.materialId, bomItemParam.directionType, bomItemParam.quantity, bomItemParam.lossCoefficient, bomItemParam.sort, bomItemParam.description);

            Bom bom = new Bom(bomNo, bomName, versionNo, productId, runSize, effectedDate, expiredDate, facilityId, description);
            bom.SetBomItems(bomItems);

            this._unitOfWork.RegisterAdd(bom);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 修改物料清单 —— void UpdateBom(Guid bomId, string bomNo...
        /// <summary>
        /// 修改物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <param name="bomNo">物料清单编号</param>
        /// <param name="bomName">物料清单名称</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        /// <param name="bomItemParams">物料清单项参数模型集</param>
        public void UpdateBom(Guid bomId, string bomNo, string bomName, string versionNo, Guid productId, decimal runSize, DateTime? effectedDate, DateTime? expiredDate, Guid? facilityId, string description, IEnumerable<BomItemParam> bomItemParams)
        {
            #region # 验证

            bomItemParams = bomItemParams?.ToArray() ?? Array.Empty<BomItemParam>();
            if (!bomItemParams.Any())
            {
                throw new ArgumentNullException(nameof(bomItemParams), "物料清单明细不可为空！");
            }

            #endregion

            IEnumerable<BomItem> bomItems =
                from bomItemParam in bomItemParams
                select new BomItem(bomItemParam.materialId, bomItemParam.directionType, bomItemParam.quantity, bomItemParam.lossCoefficient, bomItemParam.sort, bomItemParam.description);

            Bom bom = this._unitOfWork.Resolve<Bom>(bomId);
            bom.UpdateInfo(bomNo, bomName, versionNo, productId, runSize, effectedDate, expiredDate, facilityId, description);
            bom.SetBomItems(bomItems);

            this._unitOfWork.RegisterSave(bom);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 删除物料清单 —— void RemoveBom(Guid bomId)
        /// <summary>
        /// 删除物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        public void RemoveBom(Guid bomId)
        {
            Bom bom = this._unitOfWork.Resolve<Bom>(bomId);

            #region # 验证

            if (bom.CheckStatus == CheckStatus.Checking)
            {
                throw new InvalidOperationException("审核中的物料清单不可删除！");
            }
            if (bom.CheckStatus == CheckStatus.Passed)
            {
                throw new InvalidOperationException("审核通过的物料清单不可删除！");
            }

            #endregion

            this._unitOfWork.RegisterRemove(bom);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 提交审核物料清单 —— void SubmitBom(Guid bomId)
        /// <summary>
        /// 提交审核物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        public void SubmitBom(Guid bomId)
        {
            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            Bom bom = this._unitOfWork.Resolve<Bom>(bomId);
            bom.Submit(operatorAccount, operatorName);

            this._unitOfWork.RegisterSave(bom);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 批量提交审核物料清单 —— void SubmitBoms(IEnumerable<Guid>...
        /// <summary>
        /// 批量提交审核物料清单
        /// </summary>
        /// <param name="bomIds">物料清单Id集</param>
        public void SubmitBoms(IEnumerable<Guid> bomIds)
        {
            #region # 验证

            bomIds = bomIds?.Distinct().ToArray() ?? Array.Empty<Guid>();
            if (!bomIds.Any())
            {
                return;
            }

            #endregion

            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            ICollection<Bom> boms = this._unitOfWork.ResolveRange<Bom>(bomIds);
            foreach (Bom bom in boms)
            {
                bom.Submit(operatorAccount, operatorName);
            }

            this._unitOfWork.RegisterSaveRange(boms);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 审核物料清单 —— void CheckBom(Guid bomId...
        /// <summary>
        /// 审核物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <param name="passed">是否通过</param>
        /// <param name="checkedRemark">审核意见</param>
        public void CheckBom(Guid bomId, bool passed, string checkedRemark)
        {
            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            Bom bom = this._unitOfWork.Resolve<Bom>(bomId);
            bom.Check(passed, checkedRemark, operatorAccount, operatorName);

            this._unitOfWork.RegisterSave(bom);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 启用物料清单 —— void EnableBom(Guid bomId)
        /// <summary>
        /// 启用物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        public void EnableBom(Guid bomId)
        {
            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            Bom bom = this._unitOfWork.Resolve<Bom>(bomId);
            bom.Enable(operatorAccount, operatorName);

            this._unitOfWork.RegisterSave(bom);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 停用物料清单 —— void DisableBom(Guid bomId...
        /// <summary>
        /// 停用物料清单
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <param name="reason">停用原因</param>
        public void DisableBom(Guid bomId, string reason)
        {
            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            Bom bom = this._unitOfWork.Resolve<Bom>(bomId);
            bom.Disable(operatorAccount, operatorName, reason);

            this._unitOfWork.RegisterSave(bom);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 创建工艺类 —— void CreateProcessClass(string classNo, string className...
        /// <summary>
        /// 创建工艺类
        /// </summary>
        /// <param name="classNo">工艺类编号</param>
        /// <param name="className">工艺类名称</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void CreateProcessClass(string classNo, string className, Guid? facilityId, string description)
        {
            ProcessClass processClass = new ProcessClass(classNo, className, facilityId, description);

            this._unitOfWork.RegisterAdd(processClass);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 修改工艺类 —— void UpdateProcessClass(Guid processClassId, string classNo...
        /// <summary>
        /// 修改工艺类
        /// </summary>
        /// <param name="processClassId">工艺类Id</param>
        /// <param name="classNo">工艺类编号</param>
        /// <param name="className">工艺类名称</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void UpdateProcessClass(Guid processClassId, string classNo, string className, Guid? facilityId, string description)
        {
            ProcessClass processClass = this._unitOfWork.Resolve<ProcessClass>(processClassId);
            processClass.UpdateInfo(classNo, className, facilityId, description);

            this._unitOfWork.RegisterSave(processClass);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 删除工艺类 —— void RemoveProcessClass(Guid processClassId)
        /// <summary>
        /// 删除工艺类
        /// </summary>
        /// <param name="processClassId">工艺类Id</param>
        public void RemoveProcessClass(Guid processClassId)
        {
            this._unitOfWork.RegisterRemove<ProcessClass>(processClassId);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 创建工艺 —— void CreateProcess(string processNo, string processName...
        /// <summary>
        /// 创建工艺
        /// </summary>
        /// <param name="processNo">工艺编号</param>
        /// <param name="processName">工艺名称</param>
        /// <param name="processClassId">工艺类Id</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void CreateProcess(string processNo, string processName, Guid processClassId, string versionNo, Guid? productId, decimal runSize, Guid? facilityId, DateTime? effectedDate, DateTime? expiredDate, string description)
        {
            Process process = new Process(processNo, processName, processClassId, versionNo, productId, runSize, facilityId, effectedDate, expiredDate, description);

            this._unitOfWork.RegisterAdd(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 修改工艺 —— void UpdateProcess(Guid processId, string processNo...
        /// <summary>
        /// 修改工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="processNo">工艺编号</param>
        /// <param name="processName">工艺名称</param>
        /// <param name="processClassId">工艺类Id</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void UpdateProcess(Guid processId, string processNo, string processName, Guid processClassId, string versionNo, Guid? productId, decimal runSize, Guid? facilityId, DateTime? effectedDate, DateTime? expiredDate, string description)
        {
            Process process = this._unitOfWork.Resolve<Process>(processId);
            process.UpdateInfo(processNo, processName, processClassId, versionNo, productId, runSize, facilityId, effectedDate, expiredDate, description);

            this._unitOfWork.RegisterSave(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 删除工艺 —— void RemoveProcess(Guid processId)
        /// <summary>
        /// 删除工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        public void RemoveProcess(Guid processId)
        {
            Process process = this._unitOfWork.Resolve<Process>(processId);

            #region # 验证

            if (process.CheckStatus == CheckStatus.Checking)
            {
                throw new InvalidOperationException("审核中的工艺不可删除！");
            }
            if (process.CheckStatus == CheckStatus.Passed)
            {
                throw new InvalidOperationException("审核通过的工艺不可删除！");
            }

            #endregion

            this._unitOfWork.RegisterRemove(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 创建工艺段 —— void CreateProcessSegment(Guid processId, string segmentNo...
        /// <summary>
        /// 创建工艺段
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="segmentNo">工艺段编号</param>
        /// <param name="segmentName">工艺段名称</param>
        /// <param name="durationQuota">工时定额</param>
        /// <param name="directivePath">工艺指导书</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="workStationId">工位Id</param>
        /// <param name="formMode">表单模式</param>
        /// <param name="formDefinition">表单定义</param>
        /// <param name="needToInspect">是否需质检</param>
        /// <param name="sort">排序</param>
        /// <param name="description">描述</param>
        /// <param name="personRuleParams">工艺段人员规范参数模型集</param>
        /// <param name="equipmentRuleParams">工艺段设备规范参数模型集</param>
        /// <param name="materialRuleParams">工艺段物料规范参数模型集</param>
        /// <param name="parameterRuleParams">工艺段参数规范参数模型集</param>
        public void CreateProcessSegment(Guid processId, string segmentNo, string segmentName, TimeSpan durationQuota, string directivePath, Guid? facilityId, Guid? workStationId, FormMode formMode, FormDefinition formDefinition, bool needToInspect, int sort, string description, IEnumerable<SegmentPersonRuleParam> personRuleParams, IEnumerable<SegmentEquipmentRuleParam> equipmentRuleParams, IEnumerable<SegmentMaterialRuleParam> materialRuleParams, IEnumerable<SegmentParameterRuleParam> parameterRuleParams)
        {
            personRuleParams = personRuleParams?.ToArray() ?? Array.Empty<SegmentPersonRuleParam>();
            equipmentRuleParams = equipmentRuleParams?.ToArray() ?? Array.Empty<SegmentEquipmentRuleParam>();
            materialRuleParams = materialRuleParams?.ToArray() ?? Array.Empty<SegmentMaterialRuleParam>();
            parameterRuleParams = parameterRuleParams?.ToArray() ?? Array.Empty<SegmentParameterRuleParam>();
            IEnumerable<SegmentPersonRule> personRules =
                from personRuleParam in personRuleParams
                select new SegmentPersonRule(personRuleParam.personClassId, personRuleParam.personId, personRuleParam.personUse, personRuleParam.quantity, personRuleParam.facilityId, personRuleParam.sort, personRuleParam.description);
            IEnumerable<SegmentEquipmentRule> equipmentRules =
                from equipmentRuleParam in equipmentRuleParams
                select new SegmentEquipmentRule(equipmentRuleParam.equipmentClassId, equipmentRuleParam.equipmentId, equipmentRuleParam.equipmentUse, equipmentRuleParam.quantity, equipmentRuleParam.facilityId, equipmentRuleParam.sort, equipmentRuleParam.description);
            IEnumerable<SegmentMaterialRule> materialRules =
                from materialRuleParam in materialRuleParams
                select new SegmentMaterialRule(materialRuleParam.materialId, materialRuleParam.directionType, materialRuleParam.quantity, materialRuleParam.facilityId, materialRuleParam.sort, materialRuleParam.description);
            IEnumerable<SegmentParameterRule> parameterRules =
                from parameterRuleParam in parameterRuleParams
                select new SegmentParameterRule(parameterRuleParam.parameterNo, parameterRuleParam.parameterName, parameterRuleParam.relatedVariableNo, parameterRuleParam.standardValue, parameterRuleParam.maxValue, parameterRuleParam.minValue, parameterRuleParam.valueUnitNo, parameterRuleParam.facilityId, parameterRuleParam.sort, parameterRuleParam.description);

            Process process = this._unitOfWork.Resolve<Process>(processId);
            ProcessSegment processSegment = new ProcessSegment(segmentNo, segmentName, durationQuota, directivePath, facilityId, workStationId, formMode, formDefinition, needToInspect, sort, description);
            processSegment.SetPersonRules(personRules);
            processSegment.SetEquipmentRules(equipmentRules);
            processSegment.SetMaterialRules(materialRules);
            processSegment.SetParameterRules(parameterRules);
            process.AppendSegment(processSegment);

            this._unitOfWork.RegisterSave(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 修改工艺段 —— void UpdateProcessSegment(Guid processId, Guid processSegmentId...
        /// <summary>
        /// 修改工艺段
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <param name="segmentNo">工艺段编号</param>
        /// <param name="segmentName">工艺段名称</param>
        /// <param name="durationQuota">工时定额</param>
        /// <param name="directivePath">工艺指导书</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="workStationId">工位Id</param>
        /// <param name="formMode">表单模式</param>
        /// <param name="formDefinition">表单定义</param>
        /// <param name="needToInspect">是否需质检</param>
        /// <param name="sort">排序</param>
        /// <param name="description">描述</param>
        /// <param name="personRuleParams">工艺段人员规范参数模型集</param>
        /// <param name="equipmentRuleParams">工艺段设备规范参数模型集</param>
        /// <param name="materialRuleParams">工艺段物料规范参数模型集</param>
        /// <param name="parameterRuleParams">工艺段参数规范参数模型集</param>
        public void UpdateProcessSegment(Guid processId, Guid processSegmentId, string segmentNo, string segmentName, TimeSpan durationQuota, string directivePath, Guid? facilityId, Guid? workStationId, FormMode formMode, FormDefinition formDefinition, bool needToInspect, int sort, string description, IEnumerable<SegmentPersonRuleParam> personRuleParams, IEnumerable<SegmentEquipmentRuleParam> equipmentRuleParams, IEnumerable<SegmentMaterialRuleParam> materialRuleParams, IEnumerable<SegmentParameterRuleParam> parameterRuleParams)
        {
            personRuleParams = personRuleParams?.ToArray() ?? Array.Empty<SegmentPersonRuleParam>();
            equipmentRuleParams = equipmentRuleParams?.ToArray() ?? Array.Empty<SegmentEquipmentRuleParam>();
            materialRuleParams = materialRuleParams?.ToArray() ?? Array.Empty<SegmentMaterialRuleParam>();
            parameterRuleParams = parameterRuleParams?.ToArray() ?? Array.Empty<SegmentParameterRuleParam>();
            IEnumerable<SegmentPersonRule> personRules =
                from personRuleParam in personRuleParams
                select new SegmentPersonRule(personRuleParam.personClassId, personRuleParam.personId, personRuleParam.personUse, personRuleParam.quantity, personRuleParam.facilityId, personRuleParam.sort, personRuleParam.description);
            IEnumerable<SegmentEquipmentRule> equipmentRules =
                from equipmentRuleParam in equipmentRuleParams
                select new SegmentEquipmentRule(equipmentRuleParam.equipmentClassId, equipmentRuleParam.equipmentId, equipmentRuleParam.equipmentUse, equipmentRuleParam.quantity, equipmentRuleParam.facilityId, equipmentRuleParam.sort, equipmentRuleParam.description);
            IEnumerable<SegmentMaterialRule> materialRules =
                from materialRuleParam in materialRuleParams
                select new SegmentMaterialRule(materialRuleParam.materialId, materialRuleParam.directionType, materialRuleParam.quantity, materialRuleParam.facilityId, materialRuleParam.sort, materialRuleParam.description);
            IEnumerable<SegmentParameterRule> parameterRules =
                from parameterRuleParam in parameterRuleParams
                select new SegmentParameterRule(parameterRuleParam.parameterNo, parameterRuleParam.parameterName, parameterRuleParam.relatedVariableNo, parameterRuleParam.standardValue, parameterRuleParam.maxValue, parameterRuleParam.minValue, parameterRuleParam.valueUnitNo, parameterRuleParam.facilityId, parameterRuleParam.sort, parameterRuleParam.description);

            Process process = this._unitOfWork.Resolve<Process>(processId);
            ProcessSegment processSegment = process.GetSegment(processSegmentId);
            processSegment.UpdateInfo(segmentNo, segmentName, durationQuota, directivePath, facilityId, workStationId, formMode, formDefinition, needToInspect, sort, description);
            processSegment.SetPersonRules(personRules);
            processSegment.SetEquipmentRules(equipmentRules);
            processSegment.SetMaterialRules(materialRules);
            processSegment.SetParameterRules(parameterRules);

            this._unitOfWork.RegisterSave(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 删除工艺段 —— void RemoveProcessSegment(Guid processId, Guid processSegmentId)
        /// <summary>
        /// 删除工艺段
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="processSegmentId">工艺段Id</param>
        public void RemoveProcessSegment(Guid processId, Guid processSegmentId)
        {
            Process process = this._unitOfWork.Resolve<Process>(processId);
            ProcessSegment processSegment = process.GetSegment(processSegmentId);
            process.RemoveSegment(processSegment);

            this._unitOfWork.RegisterSave(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 提交审核工艺 —— void SubmitProcess(Guid processId)
        /// <summary>
        /// 提交审核工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        public void SubmitProcess(Guid processId)
        {
            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            Process process = this._unitOfWork.Resolve<Process>(processId);
            process.Submit(operatorAccount, operatorName);

            this._unitOfWork.RegisterSave(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 批量提交审核工艺 —— void SubmitProcesses(IEnumerable<Guid>...
        /// <summary>
        /// 批量提交审核工艺
        /// </summary>
        /// <param name="processIds">工艺Id集</param>
        public void SubmitProcesses(IEnumerable<Guid> processIds)
        {
            #region # 验证

            processIds = processIds?.Distinct().ToArray() ?? Array.Empty<Guid>();
            if (!processIds.Any())
            {
                return;
            }

            #endregion

            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            ICollection<Process> processs = this._unitOfWork.ResolveRange<Process>(processIds);
            foreach (Process process in processs)
            {
                process.Submit(operatorAccount, operatorName);
            }

            this._unitOfWork.RegisterSaveRange(processs);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 审核工艺 —— void CheckProcess(Guid processId...
        /// <summary>
        /// 审核工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="passed">是否通过</param>
        /// <param name="checkedRemark">审核意见</param>
        public void CheckProcess(Guid processId, bool passed, string checkedRemark)
        {
            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            Process process = this._unitOfWork.Resolve<Process>(processId);
            process.Check(passed, checkedRemark, operatorAccount, operatorName);

            this._unitOfWork.RegisterSave(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 启用工艺 —— void EnableProcess(Guid processId)
        /// <summary>
        /// 启用工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        public void EnableProcess(Guid processId)
        {
            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            Process process = this._unitOfWork.Resolve<Process>(processId);
            process.Enable(operatorAccount, operatorName);

            this._unitOfWork.RegisterSave(process);
            this._unitOfWork.Commit();
        }
        #endregion

        #region # 停用工艺 —— void DisableProcess(Guid processId...
        /// <summary>
        /// 停用工艺
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <param name="reason">停用原因</param>
        public void DisableProcess(Guid processId, string reason)
        {
            //获取当前用户
            LoginInfo loginInfo = MembershipMediator.GetLoginInfo();
            string operatorAccount = loginInfo?.LoginId;
            string operatorName = loginInfo?.RealName;

            Process process = this._unitOfWork.Resolve<Process>(processId);
            process.Disable(operatorAccount, operatorName, reason);

            this._unitOfWork.RegisterSave(process);
            this._unitOfWork.Commit();
        }
        #endregion


        //查询部分

        #region # 分页获取物料清单列表 —— PageModel<BomInfo> GetBomsByPage(string keywords...
        /// <summary>
        /// 分页获取物料清单列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="productId">产品Id</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="enabled">是否启用</param>
        /// <param name="checkStatus">审核状态</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>物料清单列表</returns>
        public PageModel<BomInfo> GetBomsByPage(string keywords, Guid? productId, Guid? facilityId, bool? enabled, CheckStatus? checkStatus, int pageIndex, int pageSize)
        {
            Facility facility = facilityId.HasValue
                ? this._repMediator.FacilityRep.SingleFully(facilityId.Value)
                : null;
            IList<Guid> relatedFacilityIds = facility?.GetDeepNodeIds();

            ICollection<Bom> boms = this._repMediator.BomRep.FindByPage(keywords, productId, relatedFacilityIds, enabled, checkStatus, pageIndex, pageSize, out int rowCount, out int pageCount);

            IEnumerable<Guid> productIds = boms.Select(x => x.ProductId);
            IEnumerable<Guid> facilityIds = boms.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, MaterialInfo> productInfos = this._repMediator.MaterialRep.Find(productIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<BomInfo> bomInfos = boms.Select(x => x.ToDTO(productInfos, facilityInfos));

            return new PageModel<BomInfo>(bomInfos, pageIndex, pageSize, pageCount, rowCount);
        }
        #endregion

        #region # 获取物料清单项列表 —— IEnumerable<BomItemInfo> GetBomItems(Guid bomId)
        /// <summary>
        /// 获取物料清单项列表
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <returns>物料清单项列表</returns>
        public IEnumerable<BomItemInfo> GetBomItems(Guid bomId)
        {
            ICollection<BomItem> bomItems = this._repMediator.BomItemRep.Find(bomId);

            IEnumerable<Guid> materialIds = bomItems.Select(x => x.MaterialId);
            IDictionary<Guid, MaterialInfo> materialInfos = this._repMediator.MaterialRep.Find(materialIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));

            IEnumerable<BomItemInfo> bomItemInfos = bomItems.Select(x => x.ToDTO(materialInfos));

            return bomItemInfos;
        }
        #endregion

        #region # 计算物料需求 —— IDictionary<Guid, decimal> CalculateMaterialAsks(Guid bomId...
        /// <summary>
        /// 计算物料需求
        /// </summary>
        /// <param name="bomId">物料清单Id</param>
        /// <param name="runSize">运行规模</param>
        /// <returns>物料需求字典</returns>
        public IDictionary<Guid, decimal> CalculateMaterialAsks(Guid bomId, decimal runSize)
        {
            Bom bom = this._repMediator.BomRep.Single(bomId);
            return this._svcMediator.BomSvc.CalculateMaterialAsks(bom, runSize);
        }
        #endregion

        #region # 分页获取工艺类列表 —— PageModel<ProcessClassInfo> GetProcessClassesByPage(string keywords...
        /// <summary>
        /// 分页获取工艺类列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>工艺类列表</returns>
        public PageModel<ProcessClassInfo> GetProcessClassesByPage(string keywords, Guid? facilityId, int pageIndex, int pageSize)
        {
            Facility facility = facilityId.HasValue
                ? this._repMediator.FacilityRep.SingleFully(facilityId.Value)
                : null;
            IList<Guid> relatedFacilityIds = facility?.GetDeepNodeIds();

            ICollection<ProcessClass> processClasses = this._repMediator.ProcessClassRep.FindByPage(keywords, relatedFacilityIds, pageIndex, pageSize, out int rowCount, out int pageCount);

            IEnumerable<Guid> facilityIds = processClasses.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<ProcessClassInfo> processClassInfos = processClasses.Select(x => x.ToDTO(facilityInfos));

            return new PageModel<ProcessClassInfo>(processClassInfos, pageIndex, pageSize, pageCount, rowCount);
        }
        #endregion

        #region # 分页获取工艺列表 —— PageModel<ProcessInfo> GetProcessesByPage(string keywords...
        /// <summary>
        /// 分页获取工艺列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="processClassId">工艺类Id</param>
        /// <param name="productId">产品Id</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="enabled">是否启用</param>
        /// <param name="checkStatus">审核状态</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <returns>工艺列表</returns>
        public PageModel<ProcessInfo> GetProcessesByPage(string keywords, Guid? processClassId, Guid? productId, Guid? facilityId, bool? enabled, CheckStatus? checkStatus, int pageIndex, int pageSize)
        {
            Facility facility = facilityId.HasValue
                ? this._repMediator.FacilityRep.SingleFully(facilityId.Value)
                : null;
            IList<Guid> relatedFacilityIds = facility?.GetDeepNodeIds();

            ICollection<Process> processes = this._repMediator.ProcessRep.FindByPage(keywords, processClassId, productId, relatedFacilityIds, enabled, checkStatus, pageIndex, pageSize, out int rowCount, out int pageCount);

            IEnumerable<Guid> processClassIds = processes.Select(x => x.ProcessClassId);
            IEnumerable<Guid> productIds = processes.Where(x => x.ProductId.HasValue).Select(x => x.ProductId.Value);
            IEnumerable<Guid> facilityIds = processes.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, ProcessClassInfo> processClassInfos = this._repMediator.ProcessClassRep.Find(processClassIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, MaterialInfo> productInfos = this._repMediator.MaterialRep.Find(productIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<ProcessInfo> processInfos = processes.Select(x => x.ToDTO(processClassInfos, productInfos, facilityInfos));

            return new PageModel<ProcessInfo>(processInfos, pageIndex, pageSize, pageCount, rowCount);
        }
        #endregion

        #region # 获取工艺/工艺段字典 —— IDictionary<Process, ProcessSegment[]> GetProcessesWithSegments()
        /// <summary>
        /// 获取工艺/工艺段字典
        /// </summary>
        /// <returns>工艺/工艺段字典</returns>
        public IDictionary<ProcessInfo, ProcessSegmentInfo[]> GetProcessesWithSegments()
        {
            IDictionary<Process, ProcessSegment[]> processes = this._repMediator.ProcessRep.FindAllWithSegments();
            IDictionary<ProcessInfo, ProcessSegmentInfo[]> processInfos = processes.ToDictionary(x => x.Key.ToDTO(null, null, null), x => x.Value.Select(y => y.ToDTO(null, null)).ToArray());

            return processInfos;
        }
        #endregion

        #region # 获取工艺段列表 —— IEnumerable<ProcessSegmentInfo> GetProcessSegments(Guid processId)
        /// <summary>
        /// 获取工艺段列表
        /// </summary>
        /// <param name="processId">工艺Id</param>
        /// <returns>工艺段列表</returns>
        public IEnumerable<ProcessSegmentInfo> GetProcessSegments(Guid processId)
        {
            IEnumerable<ProcessSegment> processSegments = this._repMediator.ProcessSegmentRep.Find(processId);

            IEnumerable<Guid> facilityIds = processSegments.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IEnumerable<Guid> workStationIds = processSegments.Where(x => x.WorkStationId.HasValue).Select(x => x.WorkStationId.Value);
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());
            IDictionary<Guid, WorkStationInfo> workStationInfos = this._repMediator.WorkStationRep.Find(workStationIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));

            IEnumerable<ProcessSegmentInfo> processSegmentInfos = processSegments.Select(x => x.ToDTO(facilityInfos, workStationInfos));

            return processSegmentInfos;
        }
        #endregion

        #region # 获取工艺段人员规范列表 —— IEnumerable<SegmentPersonRuleInfo> GetProcessSegmentPersonRules(Guid processSegmentId)
        /// <summary>
        /// 获取工艺段人员规范列表
        /// </summary>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <returns>工艺段人员规范列表</returns>
        public IEnumerable<SegmentPersonRuleInfo> GetProcessSegmentPersonRules(Guid processSegmentId)
        {
            ICollection<SegmentPersonRule> personRules = this._repMediator.SegmentPersonRuleRep.Find(processSegmentId);

            IEnumerable<Guid> personClassIds = personRules.Where(x => x.PersonClassId.HasValue).Select(x => x.PersonClassId.Value);
            IEnumerable<Guid> personIds = personRules.Where(x => x.PersonId.HasValue).Select(x => x.PersonId.Value);
            IEnumerable<Guid> facilityIds = personRules.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, PersonClassInfo> personClassInfos = this._repMediator.PersonClassRep.Find(personClassIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, PersonInfo> personInfos = this._repMediator.PersonRep.Find(personIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<SegmentPersonRuleInfo> personRuleInfos = personRules.Select(x => x.ToDTO(personClassInfos, personInfos, facilityInfos));

            return personRuleInfos;
        }
        #endregion

        #region # 获取工艺段设备规范列表 —— IEnumerable<SegmentEquipmentRuleInfo> GetProcessSegmentEquipmentRules(Guid processSegmentId)
        /// <summary>
        /// 获取工艺段设备规范列表
        /// </summary>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <returns>工艺段设备规范列表</returns>
        public IEnumerable<SegmentEquipmentRuleInfo> GetProcessSegmentEquipmentRules(Guid processSegmentId)
        {
            ICollection<SegmentEquipmentRule> equipmentRules = this._repMediator.SegmentEquipmentRuleRep.Find(processSegmentId);

            IEnumerable<Guid> equipmentClassIds = equipmentRules.Where(x => x.EquipmentClassId.HasValue).Select(x => x.EquipmentClassId.Value);
            IEnumerable<Guid> equipmentIds = equipmentRules.Where(x => x.EquipmentId.HasValue).Select(x => x.EquipmentId.Value);
            IEnumerable<Guid> facilityIds = equipmentRules.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, EquipmentClassInfo> equipmentClassInfos = this._repMediator.EquipmentClassRep.Find(equipmentClassIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, EquipmentInfo> equipmentInfos = this._repMediator.EquipmentRep.Find(equipmentIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<SegmentEquipmentRuleInfo> equipmentRuleInfos = equipmentRules.Select(x => x.ToDTO(equipmentClassInfos, equipmentInfos, facilityInfos));

            return equipmentRuleInfos;
        }
        #endregion

        #region # 获取工艺段物料规范列表 —— IEnumerable<SegmentMaterialRuleInfo> GetProcessSegmentMaterialRules(Guid processSegmentId)
        /// <summary>
        /// 获取工艺段物料规范列表
        /// </summary>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <returns>工艺段物料规范列表</returns>
        public IEnumerable<SegmentMaterialRuleInfo> GetProcessSegmentMaterialRules(Guid processSegmentId)
        {
            ICollection<SegmentMaterialRule> materialRules = this._repMediator.SegmentMaterialRuleRep.Find(processSegmentId);

            IEnumerable<Guid> materialIds = materialRules.Select(x => x.MaterialId);
            IEnumerable<Guid> facilityIds = materialRules.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, MaterialInfo> materialInfos = this._repMediator.MaterialRep.Find(materialIds).ToDictionary(x => x.Key, x => x.Value.ToDTO(null));
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<SegmentMaterialRuleInfo> materialRuleInfos = materialRules.Select(x => x.ToDTO(materialInfos, facilityInfos));

            return materialRuleInfos;
        }
        #endregion

        #region # 获取工艺段参数规范列表 —— IEnumerable<SegmentParameterRuleInfo> GetProcessSegmentParameterRules(Guid processSegmentId)
        /// <summary>
        /// 获取工艺段参数规范列表
        /// </summary>
        /// <param name="processSegmentId">工艺段Id</param>
        /// <returns>工艺段参数规范列表</returns>
        public IEnumerable<SegmentParameterRuleInfo> GetProcessSegmentParameterRules(Guid processSegmentId)
        {
            ICollection<SegmentParameterRule> parameterRules = this._repMediator.SegmentParameterRuleRep.Find(processSegmentId);

            IEnumerable<Guid> facilityIds = parameterRules.Where(x => x.FacilityId.HasValue).Select(x => x.FacilityId.Value);
            IDictionary<Guid, FacilityInfo> facilityInfos = this._repMediator.FacilityRep.Find(facilityIds).ToDictionary(x => x.Key, x => x.Value.ToDTO());

            IEnumerable<SegmentParameterRuleInfo> parameterRuleInfos = parameterRules.Select(x => x.ToDTO(facilityInfos));

            return parameterRuleInfos;
        }
        #endregion
    }
}
